package com.itsome.service;

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.itsome.annotation.FieldAnnotation;
import com.itsome.config.Constant;
import com.itsome.pojo.*;
import com.itsome.util.DBUtils;
import com.itsome.util.ExcelUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author itsome on 2021-01-10 16:21:20
 */
@Service
@Slf4j
public class ExcelServiceImpl {
    public List<?> importBuInfo(@RequestParam("file") MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        if (StringUtils.isEmpty(fileName)) {
            throw new RuntimeException("文件名不能为空！");
        }
        String name = fileName.replace(".xlsx", "");
        // 数据组织信息和热源基本信息 非空校验
        List<PartyBuOrgMsgTbl> buConfigList = Constant.buConfigMap.get(name);

        List<?> list = Lists.newArrayList();
        if ("智慧家庭运营BU".equals(name)) {
            list = ExcelUtils.synchronousRead(file, SmartHomeOperationBu.class, 0, 2);
        } else if ("自主引流运营BU".equals(name)) {
            list = ExcelUtils.synchronousRead(file, AutonomicDrainageOperationBu.class, 0, 2);
        } //...

        // 记录错误信息
        List<String> errInfoList = Lists.newArrayList();
        List<StaffBuMsgTbl> staffBuList = Lists.newArrayList();
        List<StaffExcel> staffList = Lists.newArrayList();

        // 非空校验，以及构建构建组织信息、基础信息、人员BU特定信息
        list.forEach(item -> fieldValidate(item, buConfigList, staffList, staffBuList, errInfoList));
        if (CollectionUtils.isEmpty(staffList)) {
            return errInfoList;
        }

        // 先根据身份证号查询数据库，是否存在用户信息
        List<String> idCardNoList = staffList.stream().map(StaffExcel::getIdCardNo).collect(Collectors.toList());
        Map<String, String> userIdMap = DBUtils.selectUserIdByIdCardNo(idCardNoList);

        List<StaffExcel> newStaffList = Lists.newArrayList();
        // 排除用户信息已保存
        staffList.forEach(staff -> {
            String userId = userIdMap.get(staff.getIdCardNo());
            if (StringUtils.isEmpty(userId)) {
                newStaffList.add(staff);
            }
        });
        List<StaffBuMsgTbl> newStaffBuList = Lists.newArrayList();
        staffBuList.forEach(bu -> {
            newStaffBuList.add(bu);
            String userId = userIdMap.get(bu.getIdCardNo());
            if (StringUtils.isNotEmpty(userId)) {
                bu.setUserId(userId);
            }
        });
        // 数据入库
        DBUtils.insertStaff(newStaffList);
        // staffBu信息需要upset，即存在就更新，不存在就新增
        DBUtils.insertStaffBu(newStaffBuList);
        return errInfoList;
    }

    /**
     * 空校验：包括空字符、全空格字符、空指针 （结合ParamValidator注解使用:提示用的字段名字取ParamValidator注解value值）
     * 校验对象的所有的字段
     *
     * @param obj 对象
     */
    private <T> void fieldValidate(T obj, List<PartyBuOrgMsgTbl> buConfigList, List<StaffExcel> staffList,
                                   List<StaffBuMsgTbl> staffBuList, List<String> errInfoList) {
        if (obj == null) {
            throw new RuntimeException("参数为空");
        }
        String userId = UUID.randomUUID().toString();

        Map<String, PartyBuOrgMsgTbl> nameMap = Maps.newHashMap();
        buConfigList.forEach(item -> nameMap.put(item.getName(), item));

        //通过反射获取对象里的所有字段
        Class<?> clazz = obj.getClass();
        Map<String, Field> map = getAllFields(clazz);
        try {
            Field rowField = clazz.getDeclaredField("row");
            rowField.setAccessible(true);
            String row = rowField.get(obj).toString();
            Field idCardNoField = clazz.getSuperclass().getDeclaredField("idCardNo");
            idCardNoField.setAccessible(true);
            String idCardNo = idCardNoField.get(obj).toString();
            StringBuilder empty = new StringBuilder();
            for (Map.Entry<String, Field> entry : map.entrySet()) {
                Field field = entry.getValue();
                if (field.getAnnotation(ExcelIgnore.class) != null) {
                    continue;
                }
                // 判断 BU类型是否为空
                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
                String fieldDesc = excelProperty.value()[0];
                PartyBuOrgMsgTbl config = nameMap.get(fieldDesc);
                boolean flag = false;
                if (config != null && "1".equals(config.getRequired())) {
                    flag = true;
                }
                // 获取字段上的注解，判断是否必填
                FieldAnnotation fieldAnnotation = field.getAnnotation(FieldAnnotation.class);
                boolean flag2 = false;
                if (fieldAnnotation != null) {
                    flag2 = fieldAnnotation.required();
                }
                //这里获取的值，非String，直接判断是否为null
                field.setAccessible(true);
                Object value = field.get(obj);
                StringBuilder sb = new StringBuilder();
                if (flag || flag2) {
                    if (value == null) {
                        sb.append("【").append(fieldDesc).append("】");
                    } else if (value instanceof String && StringUtils.isEmpty(value.toString())) {
                        sb.append("【").append(fieldDesc).append("】");
                    }
                }
                if (sb.length() != 0) {
                    empty.append(sb).append("、");
                    continue;
                }
                // 构建人员BU特定信息表
                if (config != null && StringUtils.isEmpty(empty.toString())) {
                    StaffBuMsgTbl staffBu = new StaffBuMsgTbl();
                    staffBu.setIdCardNo(idCardNo);
                    staffBu.setUserId(userId);
                    staffBu.setBuType(config.getBuType());
                    staffBu.setSeq(config.getSeq());
                    staffBu.setCode(config.getCode());
                    staffBu.setName(config.getName());
                    staffBu.setOption(value == null ? null : value.toString());
                    staffBu.setStatus("inactive");
                    staffBuList.add(staffBu);
                }
            }
            if (StringUtils.isNotEmpty(empty.toString())) {
                errInfoList.add("第" + row + "行，" + empty.deleteCharAt(empty.length() - 1).toString() + "为空，请检查！");
            } else {
                // 构建组织信息和基础信息
                StaffExcel staffInfo = new StaffExcel();
                BeanUtils.copyProperties(obj, staffInfo);
                staffInfo.setUserId(userId);
                staffList.add(staffInfo);
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            log.info("####excel数据非空校验异常", e);
        }
    }

    /**
     * 获取所有的字段，包括所有父类
     */
    private Map<String, Field> getAllFields(Class<?> clazz) {
        HashMap<String, Field> map = Maps.newHashMap();
        while (clazz != null) {
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field field : declaredFields) {
                map.put(field.getName(), field);
            }
            // 可以换成lambda表达式
            //map.putAll(Arrays.stream(declaredFields).collect(Collectors.toMap(Field::getName, Function.identity())));
            clazz = clazz.getSuperclass();
        }
        return map;
    }
}